﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Miner.Controllers.Interfaces;

namespace MinerMiner.Controllers
{
    class Block : IBlock
    {
        #region Members
        private bool marked = false;
        private MPoint position;
        private bool m_hasMine = false;
        private int blockSize;

        private Block left;
        private Block right;
        private Block top;
        private Block bottom;
        
        private IDrawingArea drawArea;
        #endregion

        #region Properties
        public bool HasMine
        {
            get { return m_hasMine; }
            set
            {
                if (value)
                {
                    m_hasMine = true;
                    IsEmpty = false;
                }
                else
                {
                    throw new NotImplementedException("HasMine property should not be resetable!!!");
                }
            }
        }

        public bool IsEmpty { get; set; }

        public int Value { get; set; }

        public bool WasOpened { get; private set; } 
        
        private Block Left
        {
            get{return left;} 
            set
            {
                left = value;
                if(left!=null)
                {
                    left.right = this;
                }
            }
        }
        private Block Top
        {
            get { return top; }
            set
            {
                top = value;
                if (top != null)
                {
                    top.bottom = this;
                }
            }
        }
        private Block Right
        {
            get { return right; }
            set
            {
                right = value;
                if (right != null)
                {
                    right.left = this;
                }
            }
        }
        private Block Bottom
        {
            get { return bottom; }
            set
            {
                bottom = value;
                if (bottom != null)
                {
                    bottom.top = this;
                }
            }
        }
        #endregion

        #region Events
        public event EventHandler Exploaded;
        public event EventHandler Marked;
        public event EventHandler UnMarked;
        public event EventHandler Opened; 
        #endregion

        #region Ctor
        public Block(MPoint p, int size, Block left, Block top, Block right, Block bottom, IDrawingArea area)
        {
            this.position = p;
            this.blockSize = size;
            this.Left = left;
            this.Top = top;
            this.Right = right;
            this.Bottom = bottom;
            this.IsEmpty = true;

            this.drawArea = area;
        } 
        #endregion

        #region IBlock
        public void Mark()
        {
            marked = !marked;
            if (Marked != null && UnMarked != null)
            {
                if (marked)
                {
                    drawArea.DrawMarkedBlock(position);
                    Marked(this, EventArgs.Empty);
                }
                else
                {
                    drawArea.DrawHiddenBlock(position);
                    UnMarked(this, EventArgs.Empty);
                }
            }
        }

        public void Open()
        {
            #region InnerMethods
            Action OpenNeiborBlocks = () =>
                    {
                        Action<Block> openNeibor = (block) =>
                        {
                            if (block != null && !block.HasMine)
                            {
                                block.Open();
                            }
                        };

                        openNeibor(Left);
                        openNeibor(Top);
                        openNeibor(Right);
                        openNeibor(Bottom);
                    };
            #endregion

            if (!WasOpened)
            {
                WasOpened = true;

                if (Opened != null)
                {
                    Opened(this, EventArgs.Empty);
                }
                if (marked && UnMarked != null)
                {
                    UnMarked(this, EventArgs.Empty);
                }

                if (IsEmpty)
                {
                    drawArea.DrawOpenedEmptyBlock(position);
                    OpenNeiborBlocks();
                }
                else if (HasMine)
                {
                    drawArea.DrawOpenedMineBlock(position);
                    if (Exploaded != null)
                    {
                        this.Exploaded(this, EventArgs.Empty);
                    }
                }
                else
                {
                    drawArea.DrawOpenedInfoBlock(position);
                    drawArea.DrawText(position, Value.ToString());
                }


            }
        } 
        #endregion
    }
}
